package lynn.java8;

import org.junit.Test;

/**
 * Concept:
 * lambda used often called closure.
 * In java interface has only one method is called functional interface,
 * for example the Runnable interface.
 * As the default the functional interface overwrite object's method,
 * such as equals,hashcode,to string and so on.
 * On the side,functional interface often called SAM(Single Abstract Method)
 *
 * Example:
 * Very simple example for lambda
 * ()-> 123.45 == double myMath(){return 123.45}
 */
public class AppTestLambdaDemo {


    @Test
    public void simpleLambdaWithNoArgs(){
        MyNumber myNumber;

        myNumber = () -> 123.45;

        System.out.println("A fixed value: " + myNumber.getValue());

        myNumber = () -> Math.random()*100;

        System.out.println("A random value: " + myNumber.getValue());
        System.out.println("Another random value: " + myNumber.getValue());

        /*
        * a lambda expression must be compatible with the method defined by the functional interface.
        * Therefore,this won't work;
        */
//        myNumber = () -> "123.45";
    }


    @Test
    public void simpleLambdaWithArgs(){

        NumericTest isEven = (n) -> (n % 2) == 0;

        if(isEven.test(10)) System.out.println("10 is even");
        if(!isEven.test(9)) System.out.println("9 is not even");

        /*
        * if only has one parameter the parentheses can be omit
        */
        NumericTest isNonNeg = n -> n >= 0;
        if(isNonNeg.test(1)) System.out.println("1 is non-negative");
        if(!isNonNeg.test(-1)) System.out.println("-1 is non-negative");

    }

    @Test
    public void simpleLambdaWithMultiArgs(){
        NumericTest2 isFactor = (n,d) -> (n % d) == 0;

        if(isFactor.test(10,2)) System.out.println("2 is a factor of 10");
        if(!isFactor.test(10,3)) System.out.println("3 is not a factor of 10");

    }

    @Test
    public void blockLambdaExpression(){
        NumericFunc factorial = n -> {

            int result = 1;
            for (int i = 0; i < n; i++)
                result = i * result;

            return result;
        };

        System.out.println("The factorial of 3 is " + factorial.func(3));
        System.out.println("The factorial of 5 is " + factorial.func(5));

    }


}

/**
 * a functional interface
 */
interface MyNumber{
    double getValue();
}

/**
 * a functional interface
 */
interface NumericTest{
    boolean test(int n);
}

/**
 * a functional interface
 */
interface NumericTest2{
    boolean test(int n,int d);
}

/**
 * a block functional interface
 */
interface NumericFunc{
    int func(int n);
}
